
package com.joysuch.wwyt.core.controller;

import com.joysuch.wwyt.core.bean.BaseAttachmentBean;
import com.joysuch.wwyt.core.bean.BaseImageTypeRepositoryBean;
import com.joysuch.wwyt.core.common.ajax.ResultBean;
import com.joysuch.wwyt.core.entity.BaseImageRepository;
import com.joysuch.wwyt.core.entity.BaseImageTypeRepository;
import com.joysuch.wwyt.core.enums.ImageFlag;
import com.joysuch.wwyt.core.enums.ImageTypes;
import com.joysuch.wwyt.core.repository.BaseImageTypeRepositoryDao;
import com.joysuch.wwyt.core.service.BaseImageRepositoryService;
import com.joysuch.wwyt.workflow.api.service.NewProcessService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.util.Assert;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

@RestController
@RequestMapping("/image")
@Slf4j
@Api(tags = "image 图片")
public class ImageController {

    private static final Logger logger = LoggerFactory.getLogger(ImageController.class);

    @Autowired
    private BaseImageRepositoryService imageService;
    @Autowired
    private BaseImageTypeRepositoryDao baseImageTypeRepositoryDao;
    @Autowired
    private NewProcessService newProcessService;

    @Value("${wwyt.base.serverUrl}")
    private String serverUrl;

    @Value("${wwyt.image.upload.dir}")
    private String imageUploadDir;

    @Value("${wwyt.image.upload.aiAlarm.dir}")
    private String aiAlarmImg;

    @Value("${wwyt.image.thumbnail.suffix}")
    private String imageThumbnailSuffix;

    @Value("${wwyt.image.thumbnail.width}")
    private Integer thumbnailWidth = 200;

    @Value("${wwyt.image.thumbnail.height}")
    private Integer thumbnailHeight = 300;

    @Value("${wwyt.image.upload.maxCount}")
    private Integer imageUploadMaxCount = 10;

    /**
     * 查询话题列表
     *
     * @return
     */
    @RequestMapping("/uploadImgForWE")
    @ResponseBody
    public Object uploadImageForWangEditor(MultipartHttpServletRequest request) {
        Map<String, Object> result = new HashMap<String, Object>();
        try {
            Map<String, MultipartFile> fileMap = request.getFileMap();
            if (fileMap.size() > 10) {
                Assert.state(false, "一次最多上传10张图片");
            }
            List<String> imgUrls = new ArrayList<String>(fileMap.size());
            for (Entry<String, MultipartFile> e : fileMap.entrySet()) {
                validateImageType(e.getValue(), 10 * 1024 * 1024);
                Long id = imageService.saveImage(e.getValue(), imageUploadDir, imageThumbnailSuffix, thumbnailWidth,
                        thumbnailHeight, false);
                imgUrls.add(serverUrl + "/image/view?id=" + id);
            }
            result.put("errno", 0);
            result.put("data", imgUrls);
            return result;
        } catch (Exception e) {
            e.printStackTrace();
        }
        result.put("errno", 100);
        return result;
    }

    /**
     * 查询话题列表
     *
     * @return
     */
    @RequestMapping("/upload")
    @ResponseBody
    @ApiOperation(value = "上传")
    public Object upload(MultipartHttpServletRequest request) {
        try {
            Map<String, MultipartFile> fileMap = request.getFileMap();
            String typeCode = null;
            if (request.getParameter("typeCode") != null) {
                typeCode = String.valueOf(request.getParameter("typeCode"));
            }
            if (fileMap.size() > 10) {
                Assert.state(false, "一次最多上传10张图片");
            }
            List<BaseAttachmentBean> attachments = new ArrayList<>(fileMap.size());
            boolean syncFlag = false;
            for (Entry<String, MultipartFile> e : fileMap.entrySet()) {
                if (StringUtils.isNotBlank(typeCode) && (typeCode.equals("user_cap") || typeCode.equals("staff_cap"))) {
                    syncFlag = true;
                    float fSize = e.getValue().getSize() * 1.0f / 1024;
                    Assert.isTrue(!(fSize > 300), "图标最大为300KB");
                }
                validateImageType(e.getValue(), 30 * 1024 * 1024);
                Long id = imageService.saveImage(e.getValue(), imageUploadDir, imageThumbnailSuffix, thumbnailWidth,
                        thumbnailHeight, syncFlag);
                BaseAttachmentBean bean = new BaseAttachmentBean();
                bean.setDownloadUrl(serverUrl + "/image/view?id=" + id);
                bean.setId(id);
                bean.setName(e.getValue().getOriginalFilename());
                //保存图片库
                if (StringUtils.isNotBlank(typeCode)) {
                    BaseImageTypeRepositoryBean typeBean = new BaseImageTypeRepositoryBean();
                    if (request.getParameter("typeId") != null) {
                        Long typeId = Long.valueOf(request.getParameter("typeId"));
                        typeBean.setTypeId(typeId);
                    }
                    typeBean.setTypeCode(typeCode);
                    if (request.getParameter("canDelete") != null) {
                        typeBean.setCanDelete(Integer.valueOf(request.getParameter("canDelete")));
                    }
                    typeBean.setImageId(id);
                    BaseImageTypeRepository type;
                    if (syncFlag) {
                        //同一图标不可新增多次 人员定位根据uniqueId删除的 会报错
                        List<String> codes = new ArrayList<>();
                        codes.add("user_cap");
                        codes.add("staff_cap");
                        type = baseImageTypeRepositoryDao.findByImageIdAndTypeCodes(id, codes);
                        if (type == null) {
                            type = imageService.saveImageTypeRepository(typeBean);
                        }
                    } else {
                        type = imageService.saveImageTypeRepository(typeBean);
                    }
                    bean.setTypeId(type.getId());
                    bean.setTypeCode(type.getTypeCode());
                    bean.setCanDelete(type.getCanDelete());
                }
                attachments.add(bean);
            }
            return ResultBean.success(attachments);
        } catch (Exception e) {
            logger.error("上传图片出错", e);
            return ResultBean.fail(105, "上传图片出错:" + e.getMessage());
        }
    }



    @RequestMapping("/rotateUpload")
    @ResponseBody
    @ApiOperation(value = "图片旋转上传")
    public Object rotateUpload(MultipartHttpServletRequest request) {
        try {
            Map<String, MultipartFile> fileMap = request.getFileMap();
            String typeCode = null;
            if (request.getParameter("typeCode") != null) {
                typeCode = String.valueOf(request.getParameter("typeCode"));
            }
            if (fileMap.size() > 10) {
                Assert.state(false, "一次最多上传10张图片");
            }
            List<BaseAttachmentBean> attachments = new ArrayList<>(fileMap.size());
            boolean syncFlag = false;
            for (Entry<String, MultipartFile> e : fileMap.entrySet()) {
                if (StringUtils.isNotBlank(typeCode) && (typeCode.equals("user_cap") || typeCode.equals("staff_cap"))) {
                    syncFlag = true;
                    float fSize = e.getValue().getSize() * 1.0f / 1024;
                    Assert.isTrue(!(fSize > 300), "图标最大为300KB");
                }
                validateImageType(e.getValue(), 30 * 1024 * 1024);
                Long id = imageService.saveRotateImage(e.getValue(), imageUploadDir, imageThumbnailSuffix, thumbnailWidth,
                        thumbnailHeight, syncFlag);
                BaseAttachmentBean bean = new BaseAttachmentBean();
                bean.setDownloadUrl(serverUrl + "/image/view?id=" + id);
                bean.setId(id);
                bean.setName(e.getValue().getOriginalFilename());
                //保存图片库
//                if (StringUtils.isNotBlank(typeCode)) {
//                    BaseImageTypeRepositoryBean typeBean = new BaseImageTypeRepositoryBean();
//                    if (request.getParameter("typeId") != null) {
//                        Long typeId = Long.valueOf(request.getParameter("typeId"));
//                        typeBean.setTypeId(typeId);
//                    }
//                    typeBean.setTypeCode(typeCode);
//                    if (request.getParameter("canDelete") != null) {
//                        typeBean.setCanDelete(Integer.valueOf(request.getParameter("canDelete")));
//                    }
//                    typeBean.setImageId(id);
//                    BaseImageTypeRepository type;
//                    if (syncFlag) {
//                        //同一图标不可新增多次 人员定位根据uniqueId删除的 会报错
//                        List<String> codes = new ArrayList<>();
//                        codes.add("user_cap");
//                        codes.add("staff_cap");
//                        type = baseImageTypeRepositoryDao.findByImageIdAndTypeCodes(id, codes);
//                        if (type == null) {
//                            type = imageService.saveImageTypeRepository(typeBean);
//                        }
//                    } else {
//                        type = imageService.saveImageTypeRepository(typeBean);
//                    }
//                    bean.setTypeId(type.getId());
//                    bean.setTypeCode(type.getTypeCode());
//                    bean.setCanDelete(type.getCanDelete());
//                }
                attachments.add(bean);
            }
            return ResultBean.success(attachments);
        } catch (Exception e) {
            logger.error("上传图片出错", e);
            return ResultBean.fail(105, "上传图片出错:" + e.getMessage());
        }
    }



    /**
     * 获取图片
     *
     * @return
     */
    @RequestMapping("view")
    public void image(Long id, @RequestParam(defaultValue = "origin") String type, String flag, HttpServletRequest request,
                      HttpServletResponse response) {
        try {
            BaseImageRepository image = imageService.findById(id);
            if (image == null) {
                log.error("... image view 404 error: image = null ");
                response.setStatus(404);
                response.getOutputStream().flush();
            } else {
                File imageFile;
                if (ImageTypes.THUMBNATIL.getCode().equals(type)) {
                    if (StringUtils.isNotBlank(flag) && ImageFlag.AIALARM.getCode().equals(flag)) {
                        imageFile = new File(aiAlarmImg + File.separator + image.getThumbnailPath());
                    } else {
                        imageFile = new File(imageUploadDir + File.separator + image.getThumbnailPath());
                    }
                } else {
                    if (StringUtils.isNotBlank(flag) && ImageFlag.AIALARM.getCode().equals(flag)) {
                        imageFile = new File(aiAlarmImg + File.separator + image.getOriginPath());
                    } else {
                        imageFile = new File(imageUploadDir + File.separator + image.getOriginPath());
                    }
                }
                response.setContentType(getContentType(imageFile));
                if (imageFile.exists()) {
                    byte[] cache = new byte[2048];
                    int len = 0;
                    FileInputStream fis = new FileInputStream(imageFile);
                    while ((len = fis.read(cache)) != -1) {
                        response.getOutputStream().write(cache, 0, len);
                    }
                    fis.close();
                    response.getOutputStream().flush();
                } else {
                    response.setStatus(404);
                    response.getOutputStream().flush();
                    log.error("... image view 404 error: image file not exists ");
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @RequestMapping("view-v2")
    public void imageV2(HttpServletRequest request, HttpServletResponse response, String fileUrl) {
        if (StringUtils.isEmpty(fileUrl)) {
            return;
        }
        if (fileUrl.startsWith("?id")) {
            String[] items = fileUrl.split("=");
            long id = Long.parseLong(items[1]);
            image(id, null, null, request, response);
        } else if (StringUtils.isNotEmpty(fileUrl)) {
            int i = fileUrl.lastIndexOf("/");

            String fileName = fileUrl.substring(i + 1);
            String workflowUrl = newProcessService.getWorkflowUrl();
            HttpHeaders headers = newProcessService.getHeaders();
            headers.add("Content-Type", "image/jpeg");
            HttpEntity<MultiValueMap<String, Object>> formEntity = new HttpEntity<MultiValueMap<String, Object>>(headers);
            RestTemplate restTemplate = new RestTemplate();
            // Resource类写出来，方便参考
            ResponseEntity<Resource> responseEntity = restTemplate.exchange(workflowUrl+"/api/file/sign-download?fileUrl=" + fileUrl, HttpMethod.GET, formEntity, org.springframework.core.io.Resource.class);

            InputStream inputStream = null;
            try {
                // 获取响应中的body
                inputStream = responseEntity.getBody().getInputStream();
                // 转换成流
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                byte[] buffer = new byte[1024];
                int num = inputStream.read(buffer);
                while (num != -1) {
                    baos.write(buffer, 0, num);
                    num = inputStream.read(buffer);
                }
                baos.flush();
                byte[] data = baos.toByteArray();
                // spring boot使用ServletRequestAttributes获取request或者response等
                ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
                HttpServletResponse resp = requestAttributes.getResponse();
                try {
                    resp.getOutputStream().write(data);
                    resp.getOutputStream().flush();
                    resp.getOutputStream().close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (inputStream != null) {
                    try {
                        inputStream.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }

        }

    }


    /**
     * 删除图片库
     *
     * @return
     */
    @PostMapping("deleteByTypeId")
    @ApiOperation("删除图片库")
    public ResultBean deleteByTypeId(@RequestBody List<Long> typeIds) {
        imageService.deleteByTypeId(typeIds);
        return ResultBean.success("");
    }


    /**
     * 保存图片库
     *
     * @return
     */
    @PostMapping("saveImageTypeRepository")
    @ApiOperation("保存图片库")
    public ResultBean saveType(@RequestBody BaseImageTypeRepositoryBean bean) {
        BaseImageTypeRepository repository = imageService.saveImageTypeRepository(bean);
        return ResultBean.success(repository);
    }

    /**
     * 获取图片列表
     *
     * @return
     */
    @PostMapping("list")
    @ApiOperation("获取图片库列表")
    public ResultBean list(@RequestBody List<String> typeCodes) {
        List<BaseAttachmentBean> list = imageService.list(typeCodes);
        return ResultBean.success(list);
    }

    private String getContentType(File imageFile) {
        String extension = FilenameUtils.getExtension(imageFile.getName()).toLowerCase();
        if ("jpg".equals(extension) || "jpeg".equals(extension)) {
            return "image/jpeg";
        } else if ("png".equals(extension)) {
            return "image/png";
        } else if ("gif".equals(extension)) {
            return "image/gif";
        }
        return null;
    }

    private void validateImageType(MultipartFile cover1, long size) throws IOException {
        if (!"image/jpeg".equals(cover1.getContentType())
                && !"image/png".equals(cover1.getContentType())
                && !"image/gif".equals(cover1.getContentType())
        ) {
            Assert.state(false, "只能上传jpg(jpeg)/png/gif格式图片");
        }
        if (cover1.getSize() > size) {
            Assert.state(false, "封面图片大小必须小于等于" + parseReadableSize(size));
        }
        if (this.validateWebpType(cover1).intValue()>0){
            Assert.state(false, "暂不支持WEBP格式图片");
        }
    }


    public Integer validateWebpType(MultipartFile multipartFileImageFile) throws IOException {
        // 1表示WEBP
        Integer animated = 0;
        BufferedReader br;
        String line;
        InputStream is = multipartFileImageFile.getInputStream();
        br = new BufferedReader(new InputStreamReader(is));
        // 二进制流有很多行，我们只需要读取前两行就可以判断
        int count = 0;
        while ((line = br.readLine()) != null) {
            // 为保险起见，我们读取5行
            if (line.contains("WEBP")) {
                animated = 1;
            }
            if (count++ >= 5) {
                break;
            }
        }
        return animated;
    }

    private String parseReadableSize(long size) {
        if (size > 1024 * 1024 * 1024) {
            return size * 1.0f / 1024 * 1024 * 1024 + "GB";
        } else if (size > 1024 * 1024) {
            return size * 1.0f / 1024 * 1024 + "MB";
        } else if (size > 1024) {
            return size * 1.0f / 1024 + "KB";
        } else {
            return size + "Bytes";
        }
    }

    @PostMapping("uploadLogoImage")
    @ApiOperation("上传logo图片")
    public ResultBean uploadLogoImage(@RequestBody BaseImageTypeRepositoryBean bean) {
        imageService.uploadLogoImage(bean.getImageId());
        return ResultBean.defaultSuccessResult();
    }


    @GetMapping("/getLogoImage")
    @ApiOperation("查询logo图片")
    public ResultBean getLogoImage() {
        return ResultBean.success(imageService.findLogoImage());
    }
}
